import { _decorator, Component, error, find, instantiate, Node, Prefab, resources } from 'cc';
import { UIBase } from './UIBase';
import { UIPath } from './UIConfig';
import Singleton from './Singleton';
const { ccclass, property } = _decorator;

@ccclass('UIMgr')
export class UIMgr extends Singleton<UIMgr>() {
    private _mapUI: Map<string, UIBase> = new Map();
    private _mapLayer: Map<string, Node> = new Map();
    private _initialized: boolean = false;
    //private static _instance: UIMgr = null;
    // static get instance() {
    //     if (!this._instance) {
    //         this._instance = new UIMgr();
    //         this._instance.init();
    //     }
    //     return this._instance;
    // }
    getUI<T>(uiName:string):T{
        return this._mapUI.get(uiName) as T;
    }
    private async init() {
        return new Promise<void>((resolve) => {
            let uiRoot = find("Canvas/UIRoot");
            const findLayer = (node: Node) => {
                for (let child of node.children) {
                    this._mapLayer.set(child.name, child);
                }
                this._initialized = true;
                resolve();
            };

            if (!uiRoot) {
                resources.load(UIPath.UIRoot, Prefab, (err, ret) => {
                    if (err) {
                        error(err);
                        return;
                    }
                    uiRoot = instantiate(ret);
                    uiRoot.parent = find("Canvas");
                    findLayer(uiRoot);
                });
            } else {
                findLayer(uiRoot);
            }

            // Force wait for 1 second minimum
            setTimeout(() => {
                if (!this._initialized) {
                    this._initialized = true;
                    resolve();
                }
            }, 1000);
        });
    }

    async openUI(uiName: string, layerName: string = 'Normal',callback?: () => void,...rest: any[]) {
        if (uiName.length <= 0) return;

        // Wait for initialization if not ready
        if (!this._initialized) {
            await this.init();
        }

        const args = Array.prototype.slice.call(arguments, 2);
        let ui = this._mapUI.get(uiName);

        if (!ui) {
            const layer = this._mapLayer.get(layerName);
            if (!layer) {
                error(`Layer ${layerName} not found!`);
                return;
            }

            const path = UIPath[uiName];
            if (!path) {
                error(`UI path not found for ${uiName}!`);
                return;
            }

            await new Promise<void>((resolve) => {
                resources.load(path, Prefab, (err, ret) => {
                    if (err) {
                        error(err);
                        return;
                    }
                    const uiN = instantiate(ret);
                    uiN.parent = layer;
                    ui = uiN.getComponent(UIBase);
                    this._mapUI.set(uiName, ui);
                    ui.init.apply(ui, args);
                    ui.open.apply(ui, args);
                    resolve();
                });
            });
            if (callback) {
                callback();
            }
            return;
        }

        ui.open.apply(ui, args);
        if(callback){
            callback();
        }
    }

    closeUI(uiName:string,isDestory:boolean=false,...rest:any[]) {
        if(uiName.length<=0){
            return;
        }
        let ui=this._mapUI.get(uiName);
        if(!ui){
            console.log("未找到ui");
            return;
        }
        let args = Array.prototype.slice.call(arguments,2);
        ui.isDestroy=isDestory;
        if(isDestory){
            this._mapUI.delete(uiName);
        }
        ui.close.apply(ui,args);
        // Implement your close logic here
    }
    SendMsg(msgName:string,uiName:string,...rest:any[]){
        let args = Array.prototype.slice.call(arguments,2);
        if(uiName.length <=0||!uiName){
            //没有传递UI名字，那么默认所有UI都会接收到消息。
            for(let ui of Array.from(this._mapUI.values())){
                let cb = ui[msgName];
                if(cb){
                    cb.apply(ui,args);
                    continue;
                }
                ui.handleMsg.apply(ui,args);
            }
            return;
        }
        //如果UI有传递名字，那么单独处理这个UI的响应。
        let ui = this._mapUI.get(uiName);
        if(!ui){
            error('响应的UI'+uiName+'不存在');
            return;
        }
        let cb = ui[msgName];
        if(cb){
            cb.apply(ui,args);
            return;
        }
        ui.handleMsg.apply(ui,args);        
    }
}

